package com.shbaiche.bifenba.net;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.spec.KeySpec;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

import android.annotation.SuppressLint;

/**
 * <pre>
 * 编码转换工具类
 * </pre>
 * @author lilihua
 * @version 1.0, 2013-7-18
 */
public abstract class DecodeUtil
{
	private  static final String CBC_PKCS5_PADDING = "AES/CBC/PKCS5Padding";//AES是加密方式 CBC是工作模式 PKCS5Padding是填充模式
	private  static final String AES = "AES";//AES 加密
	private  static final String  SHA1PRNG="SHA1PRNG";// SHA1PRNG 强随机种子算法, 要区别4.2以上版本的调用方法
	private final static char[] HEX = "0123456789ABCDEF".toCharArray();

	/**
	 * 通过SHA256将数据进行加密操作
	 * @param strSrc 原始字符串，即待加密字符串
	 * @return 加密后的字符串
	 */
	public static String sha256Encode(String strSrc)
	{
		String encName = "SHA-256";
		MessageDigest md = null;
		String strDes = null;

		byte[] bt = strSrc.getBytes();
		try
		{
			if (encName == null || encName.equals(""))
			{
				encName = "SHA-256";
			}
			md = MessageDigest.getInstance(encName);
			md.update(bt);
			strDes = bytes2Hex(md.digest());
		}
		catch (NoSuchAlgorithmException e)
		{
			return null;
		}
		// Log.i("main", strDes.toUpperCase());
		// System.out.println(strDes.toUpperCase());
		return strDes;
	}

	/**
	 * [将byte数组转换为16进制字符串]
	 * @param bts byte数组，即待转换的数组
	 * @return 转换后的16进制字符串
	 */
	private static String bytes2Hex(byte[] bts)
	{
		StringBuilder sb = new StringBuilder(bts.length * 2);
		for (int i = 0; i < bts.length; i++)
		{
			sb.append(HEX[bts[i] >> 4 & 0xf]);
			sb.append(HEX[bts[i] & 0xf]);
		}
		return sb.toString();

		// String des = "";
		// String tmp = null;
		// for (int i = 0; i < bts.length; i++)
		// {
		// tmp = Integer.toHexString(bts[i] & 0xFF);
		// if (tmp.length() == 1)
		// {
		// des += "0";
		// }
		// des += tmp;
		// }
		// return des;
	}

	/**
	 * [将16进制字符串转换为byte数组]
	 * @param strhex 16进制字符串
	 * @return 转换后的字节数组
	 */
	public static byte[] hex2byte(String strhex)
	{
		if (strhex == null)
		{
			return null;
		}
		int l = strhex.length();
		if (l % 2 != 0)
		{
			return null;
		}
		byte[] b = new byte[l / 2];
		for (int i = 0; i != l / 2; i++)
		{
			b[i] = (byte) Integer.parseInt(strhex.substring(i * 2, i * 2 + 2), 16);
		}
		return b;
	}

	/**
	 * [对字符串进行AES解密]
	 * @param sSrc 要解密的字符串
	 * @param sKey 解密密钥
	 * @return 解密后的字符串
	 */
	public static String decryptAES(String sSrc, String sKey)
	{
		try
		{
			byte[] raw = sKey.getBytes();
			SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
			Cipher cipher = Cipher.getInstance("AES");
			cipher.init(Cipher.DECRYPT_MODE, skeySpec);
			byte[] encrypted1 = DecodeUtil.hex2byte(sSrc);
			try
			{
				byte[] original = cipher.doFinal(encrypted1);
				String originalString = new String(original);
				return originalString;
			}
			catch (Exception e)
			{
				e.printStackTrace();
				return null;
			}
		}
		catch (Exception ex)
		{
			ex.printStackTrace();
			return null;
		}
	}

	/**
	 * <pre>
	 * 加密
	 * </pre>
	 * @param seed 种子（密钥）
	 * @param cleartext 需要加密的密文
	 * @return
	 */
	public static String encrypt(String seed, String cleartext)
	{
		try
		{
			byte[] rawKey = getRawKey(seed.getBytes());
			//byte[] rawKey = getRawKeyNew(seed);
			byte[] result = encrypt(rawKey, cleartext.getBytes());

			String password = bytes2Hex(result);

			return Base64.encode(password.getBytes());
		}
		catch (Exception e)
		{
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * <pre>
	 * 解密
	 * </pre>
	 * @param seed 种子（密钥）
	 * @param encrypted 需要解密的密文
	 * @return
	 */
	public static String decrypt(String seed, String encrypted)
	{
		try
		{
			String password = new String(Base64.decode(encrypted));

			byte[] rawKey = getRawKey(seed.getBytes());
			//byte[] rawKey = getRawKeyNew(seed);
			byte[] enc = hex2byte(password);
			byte[] result = decrypt(rawKey, enc);
			return new String(result);
		}
		catch (Exception e)
		{
			e.printStackTrace();
			return null;
		}
	}
/*
	@SuppressLint("TrulyRandom")
	private static byte[] getRawKey(byte[] seed) throws Exception
	{
		KeyGenerator kgen = KeyGenerator.getInstance("AES");
		// SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
		SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
		sr.setSeed(seed);
		kgen.init(128, sr); // 192 and 256 bits may not be available
		SecretKey skey = kgen.generateKey();
		byte[] raw = skey.getEncoded();
		return raw;
	}
*/

	// 对密钥进行处理
	private static byte[] getRawKey(byte[] seed) throws Exception {
		KeyGenerator kgen = KeyGenerator.getInstance(AES);
		//for android
		SecureRandom sr = null;
		// 在4.2以上版本中，SecureRandom获取方式发生了改变
		int sdk_version = android.os.Build.VERSION.SDK_INT;
		if(sdk_version>23){  // Android  6.0 以上
			sr = SecureRandom.getInstance(SHA1PRNG,new CryptoProvider());
		}else if(android.os.Build.VERSION.SDK_INT >= 17){   //4.2及以上
			sr = SecureRandom.getInstance(SHA1PRNG, "Crypto");
		}else {
			sr = SecureRandom.getInstance(SHA1PRNG);
		}


		// for Java
		// secureRandom = SecureRandom.getInstance(SHA1PRNG);
		sr.setSeed(seed);
		kgen.init(128, sr); //256 bits or 128 bits,192bits
		//AES中128位密钥版本有10个加密循环，192比特密钥版本有12个加密循环，256比特密钥版本则有14个加密循环。
		SecretKey skey = kgen.generateKey();
		byte[] raw = skey.getEncoded();
		return raw;
	}

	// 增加  CryptoProvider  类
	public static  class CryptoProvider extends Provider {
		/**
		 * Creates a Provider and puts parameters
		 */
		public CryptoProvider() {
			super("Crypto", 1.0, "HARMONY (SHA1 digest; SecureRandom; SHA1withDSA signature)");
			put("SecureRandom.SHA1PRNG",
					"org.apache.harmony.security.provider.crypto.SHA1PRNG_SecureRandomImpl");
			put("SecureRandom.SHA1PRNG ImplementedIn", "Software");
		}
	}

	private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception
	{
		SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
		Cipher cipher = Cipher.getInstance("AES");
		cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
		byte[] encrypted = cipher.doFinal(clear);
		return encrypted;
	}

	private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception
	{
		SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
		Cipher cipher = Cipher.getInstance("AES");
		cipher.init(Cipher.DECRYPT_MODE, skeySpec);
		byte[] decrypted = cipher.doFinal(encrypted);
		return decrypted;
	}
}
